package com.diors.commons.network;

import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

/**
 * 抽象的network处理对象
 * @author	darren.ouyang <ouyang.darren@gmail.com>
 * @date	2013-10-21
 * @version 1.0
 * @copyright Copyright (c) 2013, darren.ouyang
 */
public class NetworkHandler<T extends AbstractConnection> extends SimpleChannelHandler
{
	
	private final static Logger log = Logger.getLogger(NetworkHandler.class);
	
	private NetworkListener<T> listener;
	
	private NetworkConnectFactory<T> connFactory;
	
	public NetworkHandler (NetworkConnectFactory<T> connFactory, NetworkListener<T> listener)
	{
		this.connFactory = connFactory;
		this.listener = listener;
	}
	
	@Override
	public final void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception 
	{
		/* 新连接注册 */
		T conn = connFactory.createConnection(ctx);
		ctx.setAttachment(conn);
		
		/* 连接监听 */
		listener.connected(conn);
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public final void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception 
	{
		/* 连接关闭 */
		listener.close((T)ctx.getAttachment());
	}
	

	@SuppressWarnings("unchecked")
	@Override
	public final void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception 
	{
		/* 接收信息 */
		ChannelBuffer buff = (ChannelBuffer) e.getMessage();
		T conn = (T) ctx.getAttachment();
		
		ChannelBuffer rb = conn.readBuffer;
		if (buff.capacity() > rb.writableBytes())
		{
			listener.close(conn, "关闭连接--接收包缓冲区中含字节数量大于可写入缓冲区！！");
			return;
		}
		
		rb.writeBytes(buff);
		while (rb.readableBytes() > 4 && rb.readableBytes() >= rb.getInt(rb.readerIndex()))
		{
			boolean parseResult = listener.messageReceived(conn, rb);
			if (!parseResult)
			{
				listener.close(conn, "关闭连接--接收包解析参数失败！！");
				return;
			}
		}
		
		/* 丢弃多余部分包的数据 */
		if (rb.readable())
			rb.discardReadBytes();
		else
			rb.clear();
	}
	
	@Override
	public final void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception 
	{
		log.error(new StringBuilder("netty 错误！").toString(), e.getCause());
	}
	
}
